//go:build windows
// +build windows

package modbus

import (
	"fmt"
	"net"
	"syscall"
	"unsafe"
)

// Windows TCP Keep-Alive 结构体
type tcpKeepAlive struct {
	onOff        uint32 // 开启/关闭 Keep-Alive
	keepTime     uint32 // 空闲超时时间（毫秒）
	keepInterval uint32 // 探测间隔时间（毫秒）
}

// setTCPKeepAliveProbes 设置探测间隔和次数（Windows实现）
func (sf *TCPClientProvider) setTCPKeepAliveProbes(tcpConn *net.TCPConn) error {
	// 获取底层文件描述符
	// 注意：调用 File() 会创建一个新的文件描述符副本
	// 必须立即获取fd后关闭副本，但不能影响原始连接
	rawConn, err := tcpConn.SyscallConn()
	if err != nil {
		return fmt.Errorf("failed to get syscall conn: %v", err)
	}

	// 构建 Windows Keep-Alive 参数结构体
	ka := tcpKeepAlive{
		onOff:        1,                                           // 开启保活
		keepTime:     uint32(sf.keepAlivePeriod.Milliseconds()),   // 空闲超时（毫秒）
		keepInterval: uint32(sf.keepAliveInterval.Milliseconds()), // 探测间隔（毫秒）
	}

	var syscallErr error
	err = rawConn.Control(func(fd uintptr) {
		// 调用 WSAIoctl 设置参数
		var bytesReturned uint32
		syscallErr = syscall.WSAIoctl(
			syscall.Handle(fd),
			syscall.SIO_KEEPALIVE_VALS, // Windows Keep-Alive 控制码
			(*byte)(unsafe.Pointer(&ka)),
			uint32(unsafe.Sizeof(ka)),
			nil, // 输出缓冲区指针，设为nil表示不需要输出
			0,   // 输出缓冲区大小
			&bytesReturned,
			nil,        // 重叠结构指针，设为nil表示同步操作
			uintptr(0), // 完成例程指针，设为0表示不使用
		)
	})

	if err != nil {
		return fmt.Errorf("failed to control raw connection: %v", err)
	}

	if syscallErr != nil {
		return fmt.Errorf("failed to set Windows TCP Keep-Alive: %v", syscallErr)
	}

	sf.Debugf("Windows TCP Keep-Alive configured: keepTime=%dms, keepInterval=%dms",
		ka.keepTime, ka.keepInterval)
	return nil
}
